#include <QtGui>
#include "imageviewer.h"
#include "scrollarea.h"
#include "bookmarkdialog.h"
#include <math.h>
const int SETTINGVER=0xffff0008;
const int BOOKMARKVER=0x00000001;
const int FILEVER=0x00000001;
const QString SHOWVER = "v1.01";
#define ADDACT(_name,_text,_shortcut,_enabled,_slot) \
		_name = new QAction(_text, this);\
		_name->setShortcut(_shortcut);\
		_name->setEnabled(_enabled);\
		connect(_name, SIGNAL(triggered()), this, SLOT(_slot));
ImageViewer::ImageViewer(char *s)
{
//qDebug()()<<s;
	nowReading=0;rot=0;
	scene = new QGraphicsScene(this);
	pix = new QGraphicsPixmapItem(0,scene);
	QPalette p;
	p.setColor(QPalette::Background,QColor(45,46,47));
	scrollArea = new ScrollArea;
	flick.activateOn(scrollArea);
	scrollArea->setBackgroundRole(QPalette::Dark);
	//scrollArea->setWidget(imageLabel);
	scrollArea->setScene(scene);
	//scrollArea->setContextMenuPolicy(Qt::CustomContextMenu);
	setCentralWidget(scrollArea);
	scrollArea->setAcceptDrops(0);
	connect(scrollArea,SIGNAL(next()),this,SLOT(next()));
	connect(scrollArea,SIGNAL(prev()),this,SLOT(prev()));
	connect(scrollArea,SIGNAL(sscale(int)),this,SLOT(areaScale(int)));
	createActions();
	createMenus();
	setWindowTitle(tr("Comic Reader  ")+SHOWVER);
	resize(500, 400);
	scaleFactor = 1.0;
	setAcceptDrops(1);
	loader.setUp(&files,&folder,&nowReading);
	if(s)
	{
		load(0);
		if(!openFile(QString::fromLocal8Bit(s)))
				QMessageBox::information(this, tr("Image Viewer"),
				tr("Cannot open \"%1.\"").arg(QString::fromLocal8Bit(s)));
	}
	else load(1);
	bookMarkDialog = new BookMarkDialog(this);
	bookMarkDialog->setBookMarks(&bookmarks);
	connect(bookMarkDialog,SIGNAL(open(QString)),this,SLOT(openFile(QString)));
}
ImageViewer::~ImageViewer()
{
	delete cmenu;
	autoSave();
}
void ImageViewer::open()
{
	QString fileName = QFileDialog::getOpenFileName(this,
									tr("Open File"), QDir::currentPath(),tr("Images (*.bmp *.gif *.jpg *.jpeg *.png *.pbm *.pgm *.ppm *.tiff *.xbm *.xpm);;Everything (*.*)"));
	if(!openFile(fileName))
		QMessageBox::information(this, tr("Image Viewer"),
					tr("Cannot open \"%1.\"").arg(fileName));

}
void ImageViewer::print()
{
	Q_ASSERT(pix->pixmap());
#ifndef QT_NO_PRINTER
//! [6] //! [7]
	QPrintDialog dialog(&printer, this);
//! [7] //! [8]
	if (dialog.exec())
	{
		QPainter painter(&printer);
		QRect rect = painter.viewport();
		QSize size = pix->pixmap().size();
		size.scale(rect.size(), Qt::KeepAspectRatio);
		painter.setViewport(rect.x(), rect.y(), size.width(), size.height());
		painter.setWindow(pix->pixmap().rect());
		painter.drawPixmap(0, 0, pix->pixmap());
	}
#endif
}
void ImageViewer::zoomIn()
{
	scaleImage(1.25);
	fitToWindowAct->setChecked(0);
	fitToWindowAct->setEnabled(1);
	normalSizeAct->setEnabled(1);
	scene->setSceneRect(0,0,pix->pixmap().width(),pix->pixmap().height());

}
void ImageViewer::zoomOut()
{
	scaleImage(0.8);
	fitToWindowAct->setChecked(0);
	fitToWindowAct->setEnabled(1);
	normalSizeAct->setEnabled(1);
	scene->setSceneRect(0,0,pix->pixmap().width(),pix->pixmap().height());
}
void ImageViewer::normalSize()
{
//qDebug()()<<"normalSize";
	scaleFactor = 1.0;
	scrollArea->resetTransform();
	scrollArea->rotate(rot);
	//th=0;
	//piceditor.scalePic(1,pix->pixmap());
	normalSizeAct->setEnabled(0);
	fitToWindowAct->setChecked(0);
	fitToWindowAct->setEnabled(1);
	scene->setSceneRect(0,0,pix->pixmap().width(),pix->pixmap().height());
}
void ImageViewer::fitToWindow()
{
	normalSizeAct->setEnabled(1);
	fitToWindowAct->setEnabled(0);
	bool fit = fitToWindowAct->isChecked();
	scaleToWeigth(scrollArea->viewport()->width());
	if (!fit)
	{
		normalSize();
	}
}
void ImageViewer::about()
{
	QMessageBox::about(this, tr("About Comic Reader  ")+SHOWVER,
			tr("<p><b>Comic Reader</b> is a software for reading comics.</p>"));
}
void ImageViewer::createActions()
{
	ADDACT(openAct			,tr("&Open...")			,tr("Ctrl+O"),1,open())
	ADDACT(openFolderAct	,tr("Open &Folder...")	,tr("Ctrl+D"),1,openFolder())
	ADDACT(printAct			,tr("&Print...")		,tr("Ctrl+P"),0,print())
	ADDACT(exitAct			,tr("&Exit")			,tr("Esc")	 ,1,close())
	ADDACT(zoomInAct		,tr("Zoom &In (25%)")	,tr("Ctrl+="),0,zoomIn())
	ADDACT(zoomOutAct		,tr("Zoom &Out (25%)")	,tr("Ctrl+-"),0,zoomOut())
	ADDACT(rotateAct		,tr("&Rotate")			,tr("Ctrl+R"),0,rotate())
	ADDACT(normalSizeAct	,tr("&Normal Size")		,tr("Ctrl+F"),0,normalSize())
	ADDACT(fitToWindowAct	,tr("Fit to &Window")	,tr("Ctrl+W"),0,fitToWindow())
	ADDACT(aboutAct			,tr("&About")			,tr("")		 ,1,about())
	ADDACT(nextAct			,tr("&Next")			,tr("Ctrl+X"),0,next())
	ADDACT(prevAct			,tr("&Prev")			,tr("Ctrl+Z"),0,prev())
	ADDACT(lastAct			,tr("&Last")			,tr("Ctrl+L"),0,last())
	ADDACT(fristAct			,tr("&Frist")			,tr("Ctrl+F"),0,frist())
	ADDACT(fullScreenAct	,tr("&Full screen")		,tr("Space") ,1,fullScreen())
	ADDACT(addAct			,tr("&Add to bookmarks"),tr("Ctrl+A"),0,addBookmark())
	ADDACT(loadAct			,tr("Load &bookmarks")	,tr("Ctrl+V"),1,loadBookmark())
	ADDACT(topAct			,tr("Always on &top")	,tr("")		 ,1,onTop())
	ADDACT(nowAct			,tr("0/0")				,tr("")		 ,1,onNow)
	fitToWindowAct->setCheckable(1);
	fullScreenAct->setCheckable(1);
	topAct->setCheckable(1);
}
void ImageViewer::createMenus()
{
	fileMenu = new QMenu(tr("&File"), this);
	fileMenu->addAction(openAct);
	fileMenu->addAction(openFolderAct);
	fileMenu->addAction(printAct);
	fileMenu->addSeparator();
	fileMenu->addAction(exitAct);

	viewMenu = new QMenu(tr("&View"), this);
	viewMenu->addAction(zoomInAct);
	viewMenu->addAction(zoomOutAct);
	viewMenu->addAction(rotateAct);
	viewMenu->addAction(normalSizeAct);
	viewMenu->addSeparator();
	viewMenu->addAction(fitToWindowAct);
	viewMenu->addSeparator();



	readMenu = new QMenu(tr("&Read"),this);
	readMenu->addAction(nextAct);
	readMenu->addAction(prevAct);
	readMenu->addSeparator();
	readMenu->addAction(lastAct);
	readMenu->addAction(fristAct);

	bookMenu = new QMenu(tr("book&mark"),this);
	bookMenu->addAction(addAct);
	bookMenu->addAction(loadAct);
	readMenu->addSeparator();
	readMenu->addMenu(bookMenu);

	winMenu=new QMenu(tr("&Windows"),this);
	winMenu->addAction(fullScreenAct);
	winMenu->addAction(topAct);

	helpMenu = new QMenu(tr("&Help"), this);
	helpMenu->addAction(aboutAct);

	menuBar()->addMenu(fileMenu);
	menuBar()->addMenu(viewMenu);
	menuBar()->addMenu(readMenu);
	menuBar()->addMenu(winMenu);
	menuBar()->addMenu(helpMenu);
	menuBar()->addAction(nowAct);
	cmenu=new QMenu(this);
	cmenu->addAction(zoomInAct);
	cmenu->addAction(zoomOutAct);
	cmenu->addAction(rotateAct);
	cmenu->addAction(normalSizeAct);
	cmenu->addAction(fitToWindowAct);
	cmenu->addSeparator();
	cmenu->addAction(prevAct);
	cmenu->addAction(nextAct);
	cmenu->addAction(fristAct);
	cmenu->addAction(lastAct);
	cmenu->addSeparator();
	cmenu->addAction(addAct);
	cmenu->addAction(loadAct);
	cmenu->addSeparator();
	cmenu->addAction(fullScreenAct);
	cmenu->addSeparator();
	cmenu->addAction(exitAct);
	connect(scrollArea,SIGNAL(showCmenu()),this,SLOT(showcmenu()));
	scrollArea->setcmenu(cmenu);
}
void ImageViewer::scaleImage(double factor)
{
	//Q_ASSERT(pix->pixmap());
	scaleFactor *= factor;
	if(fabs(scaleFactor-1)<1e-5)
	{
		scaleFactor=1;
		if(!fitToWindowAct->isChecked())
			normalSizeAct->setEnabled(0);
	}else
		normalSizeAct->setEnabled(1);
	//piceditor.scalePic(scaleFactor,&pix->pixmap());
	scrollArea->scale(factor,factor);

}
void ImageViewer::adjustScrollBar(QScrollBar *scrollBar, double factor)
{
	scrollBar->setValue(int(factor * scrollBar->value()
							+ ((factor - 1) * scrollBar->pageStep()/2)));
}
void ImageViewer::resizeEvent(QResizeEvent *event)
{
	QMainWindow::resizeEvent(event);
	if(fitToWindowAct->isChecked())
		//scaleToWeigth(scrollArea->size().width()-scrollArea->verticalScrollBar()->size().width());
		scaleToWeigth(scrollArea->viewport()->width());

}
void ImageViewer::scaleToWeigth(int w)
{
	scaleImage((double)(w)/(pix->pixmap().size().width())/scaleFactor);

}
void ImageViewer::openFolder()
{
	openFolder(QFileDialog::getExistingDirectory(this,tr("open folder"),QDir::currentPath()));
}
void ImageViewer::openFolder(const QString &s)
{
	QDir currentFolder(s);
	if(!currentFolder.exists())
		return;
	QStringList filters;
	filters<<"*.bmp"<<"*.gif"<<"*.jpg"<<"*.jpeg"<<"*.png"<<"*.pbm"<<"*.pgm"<<"*.ppm"<<"*.tiff"<<"*.xbm"<<"*.xpm";
	loader.stop();
	loader.mutex.tryLock(500);
	loader.terminate();
	loader.mutex.unlock();
	clear();
	files=currentFolder.entryList(filters,QDir::Files|QDir::Readable,QDir::Name);
	folder=currentFolder.absolutePath();
	nowReading=0;
	loader.reSet();
	loader.start();
	if(!files.isEmpty())
		openNew(files.first());
	if(files.length()>1)
	{
		nextAct->setEnabled(1);
		lastAct->setEnabled(1);
	}
	onNow();
}
void ImageViewer::next()
{
	if(nowReading<files.length()-1)
	{
		openNew(files.at(++nowReading));
		prevAct->setEnabled(1);
		fristAct->setEnabled(1);
		if(nowReading==files.length()-1)
		{
			nextAct->setEnabled(0);
			lastAct->setEnabled(0);
		}
	}
}
void ImageViewer::prev()
{
	if(nowReading>0)
	{
		openNew(files.at(--nowReading));
		scrollArea->verticalScrollBar()->setValue(scrollArea->verticalScrollBar()->maximum());
		scrollArea->horizontalScrollBar()->setValue(scrollArea->horizontalScrollBar()->maximum());
		nextAct->setEnabled(1);
		lastAct->setEnabled(1);
		if(nowReading==0)
		{
			prevAct->setEnabled(0);
			fristAct->setEnabled(0);
		}
	}
}
void ImageViewer::last()
{
	if(files.length()>1)
	{
		nowReading=files.length()-1;
		openNew(files.last());
		nextAct->setEnabled(0);
		prevAct->setEnabled(1);
		lastAct->setEnabled(0);
		fristAct->setEnabled(1);
	}
}
void ImageViewer::frist()
{
	if(files.length()>1)
	{
		nowReading=0;
		openNew(files.first());
		//scrollArea->verticalScrollBar()->setValue(scrollArea->verticalScrollBar()->maximum());
		nextAct->setEnabled(1);
		prevAct->setEnabled(0);
		lastAct->setEnabled(1);
		fristAct->setEnabled(0);
	}
}
void ImageViewer::openNew(QString s)
{
	onNow();
	loader.change();
	if(!loader.runing)
	{
		//qDebug()<<"not start";
		loader.start();
	}
	if(loader.mutexs)
		loader.mutexs[nowReading].lock();
	if(loader.mutexs && loader.pics && loader.pics[nowReading])
	{
	//qDebug()()<<"load from memory";
		pix->setPixmap(*loader.pics[nowReading]);
		loader.mutexs[nowReading].unlock();
	}
	else
	{
	//qDebug()()<<"load from disk";
		if(loader.mutexs)
			loader.mutexs[nowReading].unlock();
		QString fileName=folder+"/"+s;
		if (fileName.isEmpty())
			return;
		QImage image(fileName);
		if (image.isNull())
		{
			QMessageBox::information(this, tr("Image Viewer"),
						tr("Cannot load %1.").arg(fileName));
			return;
		}
		pix->setPixmap(QPixmap::fromImage(image));
	}
	scene->setSceneRect(0,0,pix->pixmap().width(),pix->pixmap().height());
	scrollArea->horizontalScrollBar()->setValue(0);
	scrollArea->verticalScrollBar()->setValue(0);
	printAct->setEnabled(true);
	fitToWindowAct->setEnabled(true);
	zoomInAct->setEnabled(scaleFactor < 3.0);
	zoomOutAct->setEnabled(scaleFactor > 0.333);
	rotateAct->setEnabled(1);
	addAct->setEnabled(1);
	if (fitToWindowAct->isChecked())
		scaleToWeigth(scrollArea->viewport()->width());
	//else
		//scaleImage(1);
}
void ImageViewer::dragEnterEvent(QDragEnterEvent *event)
{
	if (event->mimeData()->hasFormat("text/uri-list"))
	{
			event->acceptProposedAction();
	}

}
void ImageViewer::dropEvent(QDropEvent *event)
{
	QList<QUrl> urls = event->mimeData()->urls();
		if (urls.isEmpty())
	{
		return;
	}
	QString fileName=urls.first().toLocalFile();
	if(!fileName.isEmpty())
	{
		if(!openFile(fileName))
		{
			openFolder(fileName);
		}
	}
}
void ImageViewer::clear()
{
	scaleFactor=1;
	//pix->clear();
	zoomInAct->setEnabled(false);
	zoomOutAct->setEnabled(false);
	normalSizeAct->setEnabled(false);
	fitToWindowAct->setEnabled(false);
	nextAct->setEnabled(false);
	prevAct->setEnabled(false);
	lastAct->setEnabled(0);
	fristAct->setEnabled(0);
	rotateAct->setEnabled(false);
	addAct->setEnabled(0);
}
void ImageViewer::fullScreen()
{
	if(fullScreenAct->isChecked())
	{
		showFullScreen();
		//menuBar()->setVisible(0);
	}else
	{
		showNormal();
		//menuBar()->setVisible(1);
	}
}
void ImageViewer::rotate()
{
	scrollArea->rotate(90);
	rot+=90;
	rot%=360;
}
void ImageViewer::autoSave()
{
	QFile f("autosave");
	if(f.open(QIODevice::WriteOnly))
	{
		QDataStream s(&f);
		s<<SETTINGVER
		 <<scaleFactor
		 <<topAct->isChecked()
		 <<fullScreenAct->isChecked();
	}
	QFile f2("file");
	if(f2.open(QIODevice::WriteOnly))
	{
		QDataStream s(&f2);
		s<<FILEVER;
		if(folder.isEmpty() || files.isEmpty())
		{
			s<<QString("NoFile");
		}else
			s<<folder+"/"+files.at(nowReading);
	}
	QFile f3("bookmark");
	if(f3.open(QIODevice::WriteOnly))
	{
		QDataStream s(&f3);
		s<<BOOKMARKVER<<bookmarks;
	}
}
void ImageViewer::load(bool loadFile)
{
	QFile f("autosave");
	if(f.open(QIODevice::ReadOnly))
	{
		int v;
		QDataStream s(&f);
		s>>v;
		if(v==SETTINGVER)
		{
			s>>scaleFactor;
			bool b;
			s>>b;
		//QDebug()<<b;
			topAct->setChecked(b);
			onTop();
			s>>b;
		//QDebug()<<b;
			fullScreenAct->setChecked(b);
			fullScreen();
		}
	}
	QFile f3("bookmark");
	if(f3.open(QIODevice::ReadOnly))
	{
		QDataStream s(&f3);
		int v;
		s>>v;
		if(v==BOOKMARKVER)
			s>>bookmarks;
	}
	if(loadFile)
	{
		QFile f2("file");
		if(f2.open(QIODevice::ReadOnly))
		{
			int v;
			QDataStream s(&f2);
			s>>v;
			if(v==FILEVER)
			{
				QString fileName;
				s>>fileName;
				openFile(fileName);
				scaleImage(1);
			}
		}
	}
}

bool ImageViewer::openFile(const QString &fileName)
{
	qDebug()<<"mopen";
	if (!fileName.isEmpty() && fileName!="NoFile")
	{
		QImage image(fileName);
		if (image.isNull())
		{
			return 0;
		}
		pix->setPixmap(QPixmap::fromImage(image));
		loader.stop();
		loader.mutex.tryLock(500);
		loader.terminate();
		loader.mutex.unlock();
		onNow();
		scaleFactor=1;
		rotateAct->setEnabled(1);
		zoomInAct->setEnabled(1);
		zoomOutAct->setEnabled(1);
		addAct->setEnabled(1);
		//imageLabel->setPixmap(QPixmap::fromImage(image));
		printAct->setEnabled(true);
		fitToWindowAct->setEnabled(true);
		if (fitToWindowAct->isChecked())
			scaleToWeigth(scrollArea->viewport()->width());
		else
			normalSize();
		//	imageLabel->adjustSize();
		QStringList filters;
		filters<<"*.bmp"<<"*.gif"<<"*.jpg"<<"*.jpeg"<<"*.png"<<"*.pbm"<<"*.pgm"<<"*.ppm"<<"*.tiff"<<"*.xbm"<<"*.xpm";
		QDir currentFolder=fileName;
		currentFolder.cdUp();
		files=currentFolder.entryList(filters,QDir::Files|QDir::Readable,QDir::Name);
		folder=currentFolder.absolutePath();
		nowReading=0;
		nextAct->setEnabled(0);
		prevAct->setEnabled(0);
		lastAct->setEnabled(0);
		fristAct->setEnabled(0);

		foreach(QString s,files)
		{
			if(folder+"/"+s==fileName)
				break;
			nowReading++;
		}
		if(nowReading>0)
		{
			prevAct->setEnabled(1);
			fristAct->setEnabled(1);
		}
		if(nowReading<files.length()-1)
		{
			nextAct->setEnabled(1);
			lastAct->setEnabled(1);
		}
		onNow();
		//qDebug()<<"befoar set";
		loader.reSet();
		//qDebug()<<"before run";
		loader.start();
		return 1;
	}
	return 0;
}
void ImageViewer::showcmenu()
{
	cmenu->exec(QCursor::pos()+QPoint(1,1));
}
void ImageViewer::addBookmark()
{
	if(folder.isEmpty() || files.isEmpty())
		return;
	bookmarks.append(folder+"/"+files.at(nowReading));
	QMessageBox::information(this,tr("Add bookmark"),tr("Succeed adding bookmark"));
}
void ImageViewer::loadBookmark()
{
	bookMarkDialog->upDateBookMarks();
	bookMarkDialog->exec();
}
void ImageViewer::areaScale(int d)
{
	//qDebug()<<d;
	scaleImage(pow(1.25,d/240.0));
	normalSizeAct->setEnabled(1);
}
void ImageViewer::keyPressEvent(QKeyEvent *e)
{
	if(e->key()==Qt::Key_Escape)
		close();
	else if(e->key()==Qt::Key_F12 || e->key()==Qt::Key_Space)
	{
		fullScreenAct->setChecked(!fullScreenAct->isChecked());
		fullScreen();
	//QDebug()<<"F12";
	}else if(e->key()==Qt::Key_F1)
	{
		showMinimized();
		//this->setHidden(!this->isHidden());
	}else
		QMainWindow::keyPressEvent(e);
}
void ImageViewer::onTop()
{
	if(topAct->isChecked())
	{
		setWindowFlags(Qt::WindowStaysOnTopHint);
		show();
	}else
	{
		setWindowFlags(Qt::Window);
		show();
	}
}
void ImageViewer::onNow()
{
	QString s;
	s.sprintf("%d/%d",nowReading+1,files.length());
	nowAct->setText(s);
}
